package com.merry.postProcessor.bean;

import java.beans.PropertyDescriptor;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.lang.Nullable;

/**
 * 子接口： {@link BeanPostProcessor} 的子接口，提供了一个 初始化之前的回调和初始化之后的回调。
 *  这里的初始化指的是 通过反射创建对象。也就是说，在调用在这个接口的 前置 方法 时，这个对象还没有通过反射创建好。
 *  在创建bean {@code createBean} 方法中有一段逻辑。
 *  <p>1.首先先调用 这个接口的 前置处理方法。创建一个bean。如果创建成功了。则调用 这个接口的 后置处理方法，初始化这个bean。之后返回，不执行后续的 createBean 流程。</p>
 *  <p>2.如果这个接口的 前置处理方法 没有创建一个对象，则不执行 该接口的 后置处理方法， 并且 会执行 createBean 的后续流程。 </p>
 *  <p>通常，这个接口的实现类，与 AOP 动态代理息息相关。
 *
 * <p><b>注意：</b>此接口是一个专用接口，主要用于框架内部的使用，建议用户尽可能的实现普通的 {@link BeanPostProcessor} 接口，
 * 或者从 {@link InstantiationAwareBeanPostProcessorAdapter} 派生，以进行屏蔽这个类中的两个方法。</p>
 */
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    /**
     * <p>支持这个 BeanPostProcessor 在 目标类实例化之前调用，它会返回一个 bean 对象，这个对象可能是一个 代理对象，而不是目标对象。
     * <p>如果一个非空的对象在这个方法中返回了，那么创建bean {@link AbstractBeanFactory#createBean} 的流程将被中断，
     *      它最后只会执行一次 {@link #postProcessAfterInstantiation} 后置处理方法。
     * <p>用户也许应该继承 {@link SmartInstantiationAwareBeanPostProcessor} 而不是这个接口。
     * <p>这个默认的实现是返回一个 {@code null}
     */
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    /**
     * <p>在bean实例化后，通过构造函数或工厂方法执行操作，但在Spring属性填充（从显式属性或自动连接）发生之前。也就是说，它的调用时机是在
     *  {@link #postProcessBeforeInstantiation} 方法之后执行的（只要这个方法不返回一个 {@code null} ）。
     */
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    /**
     * 属性注入之前调用的方法。
     */
    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {

        return null;
    }

    /**
     * 已弃用：属性注入之前调用的方法。
     */
    @Deprecated
    @Nullable
    default PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

        return pvs;
    }

}

